use crate::DevCommands;
use indicatif::{ProgressBar, ProgressStyle};
use std::fs;
use std::path::Path;
use walkdir::WalkDir;
use syntect::parsing::SyntaxSet;
use syntect::highlighting::ThemeSet;
use syntect::html::highlighted_html_for_string;
use git2::Repository;

pub fn handle_dev_commands(command: DevCommands, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    match command {
        DevCommands::Stats { directory, language, exclude } => {
            code_stats(&directory, language.as_deref(), &exclude, verbose)?;
        },
        DevCommands::Format { path, type_ } => {
            format_code(&path, &type_, verbose)?;
        },
        DevCommands::Lint { path, type_ } => {
            lint_code(&path, &type_, verbose)?;
        },
        DevCommands::Git { operation, repo } => {
            git_operations(&operation, &repo, verbose)?;
        },
    }
    Ok(())
}

fn code_stats(directory: &Path, language: Option<&str>, exclude: &[String], verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let pb = ProgressBar::new_spinner();
    pb.set_message("分析代码...");
    
    let mut total_files = 0;
    let mut total_lines = 0;
    let mut total_chars = 0;
    let mut code_lines = 0;
    let mut comment_lines = 0;
    let mut blank_lines = 0;
    let mut file_types = std::collections::HashMap::new();
    
    for entry in WalkDir::new(directory).into_iter().filter_map(|e| e.ok()) {
        if entry.file_type().is_file() {
            let path = entry.path();
            let filename = path.file_name().unwrap_or_default().to_string_lossy();
            
            // 检查排除模式
            let should_exclude = exclude.iter().any(|pattern| {
                path.to_string_lossy().contains(pattern) || filename.contains(pattern)
            });
            
            if should_exclude {
                continue;
            }
            
            // 检查语言过滤
            if let Some(lang) = language {
                if !is_language_file(path, lang) {
                    continue;
                }
            }
            
            if let Ok(contents) = fs::read_to_string(path) {
                total_files += 1;
                let lines = contents.lines().count();
                total_lines += lines;
                total_chars += contents.chars().count();
                
                let (code, comments, blank) = analyze_code_lines(&contents);
                code_lines += code;
                comment_lines += comments;
                blank_lines += blank;
                
                // 统计文件类型
                if let Some(ext) = path.extension() {
                    let ext_str = ext.to_string_lossy().to_lowercase();
                    *file_types.entry(ext_str).or_insert(0) += 1;
                }
                
                if verbose {
                    println!("分析: {} ({} 行)", path.display(), lines);
                }
            }
        }
        pb.tick();
    }
    
    pb.finish_with_message("✅ 分析完成");
    
    println!("📊 代码统计结果:");
    println!("  总文件数: {}", total_files);
    println!("  总行数: {}", total_lines);
    println!("  总字符数: {}", total_chars);
    println!("  代码行数: {}", code_lines);
    println!("  注释行数: {}", comment_lines);
    println!("  空行数: {}", blank_lines);
    
    if !file_types.is_empty() {
        println!("  文件类型分布:");
        let mut sorted_types: Vec<_> = file_types.iter().collect();
        sorted_types.sort_by(|a, b| b.1.cmp(a.1));
        for (ext, count) in sorted_types {
            println!("    .{}: {} 个文件", ext, count);
        }
    }
    
    Ok(())
}

fn format_code(path: &Path, type_: &str, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let pb = ProgressBar::new_spinner();
    pb.set_message("格式化代码...");
    
    if path.is_file() {
        format_single_file(path, type_, verbose)?;
    } else if path.is_dir() {
        for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
            if entry.file_type().is_file() {
                if let Some(ext) = entry.path().extension() {
                    let ext_str = ext.to_string_lossy().to_lowercase();
                    if matches_file_type(&ext_str, type_) {
                        format_single_file(entry.path(), type_, verbose)?;
                    }
                }
            }
            pb.tick();
        }
    }
    
    pb.finish_with_message("✅ 格式化完成");
    Ok(())
}

fn format_single_file(file: &Path, type_: &str, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let contents = fs::read_to_string(file)?;
    let formatted = match type_ {
        "rust" => {
            // 简单的 Rust 格式化
            format_rust_code(&contents)
        },
        "json" => {
            let json_value: serde_json::Value = serde_json::from_str(&contents)?;
            serde_json::to_string_pretty(&json_value)?
        },
        "xml" => {
            format_xml_code(&contents)?
        },
        "yaml" => {
            let yaml_value: serde_yaml::Value = serde_yaml::from_str(&contents)?;
            serde_yaml::to_string(&yaml_value)?
        },
        _ => contents,
    };
    
    if formatted != contents {
        fs::write(file, formatted)?;
        if verbose {
            println!("格式化: {}", file.display());
        }
    }
    
    Ok(())
}

fn lint_code(path: &Path, type_: &str, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let pb = ProgressBar::new_spinner();
    pb.set_message("检查代码...");
    
    let mut issues = Vec::new();
    
    if path.is_file() {
        lint_single_file(path, type_, &mut issues, verbose)?;
    } else if path.is_dir() {
        for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
            if entry.file_type().is_file() {
                if let Some(ext) = entry.path().extension() {
                    let ext_str = ext.to_string_lossy().to_lowercase();
                    if matches_file_type(&ext_str, type_) {
                        lint_single_file(entry.path(), type_, &mut issues, verbose)?;
                    }
                }
            }
            pb.tick();
        }
    }
    
    pb.finish_with_message("✅ 检查完成");
    
    if issues.is_empty() {
        println!("✅ 没有发现代码问题");
    } else {
        println!("❌ 发现 {} 个问题:", issues.len());
        for issue in issues {
            println!("  {}", issue);
        }
    }
    
    Ok(())
}

fn lint_single_file(file: &Path, type_: &str, issues: &mut Vec<String>, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let contents = fs::read_to_string(file)?;
    
    match type_ {
        "syntax" => {
            check_syntax_issues(&contents, file, issues);
        },
        "style" => {
            check_style_issues(&contents, file, issues);
        },
        "security" => {
            check_security_issues(&contents, file, issues);
        },
        _ => {}
    }
    
    if verbose && !issues.is_empty() {
        println!("检查: {} ({} 个问题)", file.display(), issues.len());
    }
    
    Ok(())
}

fn git_operations(operation: &str, repo: &Path, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let repository = Repository::open(repo)?;
    
    match operation {
        "status" => {
            git_status(&repository, verbose)?;
        },
        "log" => {
            git_log(&repository, verbose)?;
        },
        "diff" => {
            git_diff(&repository, verbose)?;
        },
        "blame" => {
            git_blame(&repository, verbose)?;
        },
        _ => return Err("不支持的 Git 操作".into()),
    }
    
    Ok(())
}

fn git_status(repo: &Repository, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let mut status_options = git2::StatusOptions::new();
    status_options.include_ignored(false);
    status_options.include_untracked(true);
    
    let statuses = repo.statuses(Some(&mut status_options))?;
    
    println!("📋 Git 状态:");
    println!("  分支: {}", repo.head()?.shorthand().unwrap_or("detached"));
    
    let mut modified = Vec::new();
    let mut added = Vec::new();
    let mut deleted = Vec::new();
    let mut untracked = Vec::new();
    
    for entry in statuses.iter() {
        let path = entry.path().unwrap_or("");
        match entry.status() {
            s if s.is_index_modified() => modified.push(path),
            s if s.is_index_new() => added.push(path),
            s if s.is_index_deleted() => deleted.push(path),
            s if s.is_wt_new() => untracked.push(path),
            _ => {}
        }
    }
    
    if !modified.is_empty() {
        println!("  已修改: {:?}", modified);
    }
    if !added.is_empty() {
        println!("  已添加: {:?}", added);
    }
    if !deleted.is_empty() {
        println!("  已删除: {:?}", deleted);
    }
    if !untracked.is_empty() {
        println!("  未跟踪: {:?}", untracked);
    }
    
    Ok(())
}

fn git_log(repo: &Repository, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let head = repo.head()?.peel_to_commit()?;
    let mut revwalk = repo.revwalk()?;
    revwalk.push(head.id())?;
    
    println!("📜 Git 提交历史:");
    
    let mut count = 0;
    for commit_id in revwalk.take(10) {
        let commit = repo.find_commit(commit_id?)?;
        let author = commit.author();
        let message = commit.message().unwrap_or("");
        
        println!("  {} {} - {}", 
            &commit.id().to_string()[..8],
            author.name().unwrap_or("Unknown"),
            message.lines().next().unwrap_or(""));
        
        count += 1;
    }
    
    if verbose {
        println!("  显示最近 {} 条提交", count);
    }
    
    Ok(())
}

fn git_diff(repo: &Repository, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let head = repo.head()?.peel_to_tree()?;
    let index = repo.index()?;
    let index_tree = repo.find_tree(index.write_tree()?)?;
    
    let diff = repo.diff_tree_to_tree(Some(&head), Some(&index_tree), None)?;
    
    println!("📊 Git 差异:");
    
    let mut files_changed = 0;
    let mut insertions = 0;
    let mut deletions = 0;
    
    for delta in diff.deltas() {
        files_changed += 1;
        if let Some(path) = delta.new_file().path() {
            println!("  {}", path.display());
        }
    }
    
    for hunk in diff.hunks() {
        for line in hunk.lines() {
            match line.origin() {
                '+' => insertions += 1,
                '-' => deletions += 1,
                _ => {}
            }
        }
    }
    
    println!("  {} 个文件变更, +{} 行, -{} 行", files_changed, insertions, deletions);
    
    Ok(())
}

fn git_blame(repo: &Repository, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    println!("📝 Git 责任追踪:");
    println!("  功能暂未实现，需要指定具体文件");
    Ok(())
}

// 辅助函数
fn is_language_file(path: &Path, language: &str) -> bool {
    if let Some(ext) = path.extension() {
        let ext_str = ext.to_string_lossy().to_lowercase();
        matches!(language, 
            "rust" if ext_str == "rs" ||
            "javascript" if ext_str == "js" ||
            "typescript" if ext_str == "ts" ||
            "python" if ext_str == "py" ||
            "java" if ext_str == "java" ||
            "cpp" if ext_str == "cpp" || ext_str == "cc" ||
            "c" if ext_str == "c" ||
            "go" if ext_str == "go"
        )
    } else {
        false
    }
}

fn matches_file_type(ext: &str, type_: &str) -> bool {
    match type_ {
        "rust" => ext == "rs",
        "json" => ext == "json",
        "xml" => ext == "xml",
        "yaml" => ext == "yaml" || ext == "yml",
        _ => false,
    }
}

fn analyze_code_lines(contents: &str) -> (usize, usize, usize) {
    let mut code = 0;
    let mut comments = 0;
    let mut blank = 0;
    
    for line in contents.lines() {
        let trimmed = line.trim();
        if trimmed.is_empty() {
            blank += 1;
        } else if trimmed.starts_with("//") || trimmed.starts_with("#") || trimmed.starts_with("/*") {
            comments += 1;
        } else {
            code += 1;
        }
    }
    
    (code, comments, blank)
}

fn format_rust_code(code: &str) -> String {
    // 简单的 Rust 代码格式化
    let mut formatted = String::new();
    let mut indent = 0;
    
    for line in code.lines() {
        let trimmed = line.trim();
        if trimmed.starts_with('}') {
            indent = indent.saturating_sub(1);
        }
        
        formatted.push_str(&"  ".repeat(indent));
        formatted.push_str(trimmed);
        formatted.push('\n');
        
        if trimmed.ends_with('{') {
            indent += 1;
        }
    }
    
    formatted
}

fn format_xml_code(xml: &str) -> Result<String, Box<dyn std::error::Error>> {
    // 简单的 XML 格式化
    let mut formatted = String::new();
    let mut indent = 0;
    let mut in_tag = false;
    
    for ch in xml.chars() {
        match ch {
            '<' => {
                if in_tag {
                    formatted.push('\n');
                    formatted.push_str(&"  ".repeat(indent));
                }
                formatted.push(ch);
                in_tag = true;
            },
            '>' => {
                formatted.push(ch);
                in_tag = false;
                if formatted.ends_with("/>") {
                    formatted.push('\n');
                } else if formatted.ends_with("</") {
                    indent = indent.saturating_sub(1);
                    formatted.push('\n');
                } else {
                    indent += 1;
                    formatted.push('\n');
                }
            },
            _ => {
                formatted.push(ch);
            },
        }
    }
    
    Ok(formatted)
}

fn check_syntax_issues(code: &str, file: &Path, issues: &mut Vec<String>) {
    // 简单的语法检查
    let mut brace_count = 0;
    let mut paren_count = 0;
    
    for (line_num, line) in code.lines().enumerate() {
        for ch in line.chars() {
            match ch {
                '{' => brace_count += 1,
                '}' => brace_count -= 1,
                '(' => paren_count += 1,
                ')' => paren_count -= 1,
                _ => {}
            }
        }
        
        if brace_count < 0 {
            issues.push(format!("{}:{}: 多余的右大括号", file.display(), line_num + 1));
        }
        if paren_count < 0 {
            issues.push(format!("{}:{}: 多余的右括号", file.display(), line_num + 1));
        }
    }
    
    if brace_count != 0 {
        issues.push(format!("{}: 大括号不匹配", file.display()));
    }
    if paren_count != 0 {
        issues.push(format!("{}: 括号不匹配", file.display()));
    }
}

fn check_style_issues(code: &str, file: &Path, issues: &mut Vec<String>) {
    // 简单的代码风格检查
    for (line_num, line) in code.lines().enumerate() {
        if line.len() > 120 {
            issues.push(format!("{}:{}: 行长度超过120字符", file.display(), line_num + 1));
        }
        
        if line.ends_with(' ') {
            issues.push(format!("{}:{}: 行尾有多余空格", file.display(), line_num + 1));
        }
        
        if line.contains('\t') {
            issues.push(format!("{}:{}: 使用制表符而非空格", file.display(), line_num + 1));
        }
    }
}

fn check_security_issues(code: &str, file: &Path, issues: &mut Vec<String>) {
    // 简单的安全检查
    let dangerous_patterns = [
        "eval(",
        "exec(",
        "system(",
        "shell_exec(",
        "passthru(",
        "file_get_contents(",
        "fopen(",
        "include(",
        "require(",
    ];
    
    for (line_num, line) in code.lines().enumerate() {
        for pattern in &dangerous_patterns {
            if line.contains(pattern) {
                issues.push(format!("{}:{}: 潜在的安全风险: {}", file.display(), line_num + 1, pattern));
            }
        }
    }
}

